Skip to content

perf: MD outline ~15× + full parse ~8× via line scanner - #145

Merged
tiensonqin merged 8 commits into
masterfrom
logseq/parser-perf-10x-c55d
Aug 30, 2026
Merged

perf: MD outline ~15× + full parse ~8× via line scanner#145
tiensonqin merged 8 commits into
masterfrom
logseq/parser-perf-10x-c55d

Conversation

@tiensonqin

@tiensonqin tiensonqin commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Optimize logseq/mldoc Markdown parsing for the Logseq hot path (outline-first, then full).

Performance (1.2MB examples/logseq_large.md, 3-iter avg, same machine)

Mode master this branch speedup
parse_outline_only 0.354s 0.024s ~15×
Full Markdown 0.479s 0.063s ~7.6×

Approach

  • Research: Evaluated Parseff (OCaml 5.3+ effects). Faster on JSON/CSV-style benches, but slower than Angstrom on short Logseq inline titles (look_ahead + effects). Not adopted; algorithmic cuts matter more here.
  • parse_outline_only: Skip heavy nested inline once block type is known. Outline keeps tags / [[page]] / ((block)) / nested page refs; drops emphasis and similar.
  • Md_outline: Line-oriented MD document parser (no Angstrom block choice backtracking). Used for outline and full Markdown.
  • Full mode: Same scanner with Inline.parse, fenced Src (language/options/pos_meta), latex env, quote continuation, heading anchors.
  • Inline fast path: Pure-OCaml try_fast_md_inline / Outline_inline.try_fast_scan for plain/tag/page/block refs; nested [[a [[b]]]] falls back to Nested_link.
  • Properties: key:: / :PROPERTIES: / #+NAME: with Property.property_references (nested refs + quoted values) in both modes.

Tests

dune runtest green (markdown, outline markdown, org, zip, export-md, export-opml).

Test plan

  • dune runtest
  • dune exec ./bench/time_parse.exe vs master
  • Logseq integration smoke (outline load + full parse)
Open in Web Open in Cursor 

Outline mode now extracts only node refs, tags, and properties:
- Fast direct scanner for #tag / [[page]] / ((block))
- Markdown-specific outline parser with peek dispatch
- Skip front-matter probing and position tracking on outline path
- Lighter heading title lookahead and outline inline pre-checks

Also adds bench/time_parse.exe for Logseq-sized Markdown fixtures.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

cursoragent and others added 2 commits August 29, 2026 09:32
Replace Angstrom block choice for MD outline with a dedicated line
scanner (headings, properties, lists, quotes, fences, footnotes) while
keeping Outline_inline for refs/tags. Fixes parse_md_outline empty-title
edge cases via the new path. ~0.026s vs ~0.30s master on 1.2MB fixture.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
@cursor cursor Bot changed the title perf: outline_only Markdown ~2.2x + structure for further gains perf: Markdown outline_only ~12x via line-oriented parser Aug 29, 2026
Tried Parseff (OCaml 5.3 effects) for MD Inline: ~4x slower than
Angstrom on short Logseq titles (effects/look_ahead overhead), so not
adopted.

Instead add a pure-OCaml MD Inline fast path (plain/#tag/[[page]]/
((block))) with Angstrom fallback. Full parse ~0.19s vs ~0.43s master
(~2.3x) on the 1.2MB fixture; outline stays ~15x.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
@cursor cursor Bot changed the title perf: Markdown outline_only ~12x via line-oriented parser perf: MD outline ~15x + full Inline fast path (~2.3x) Aug 29, 2026
cursoragent and others added 3 commits August 29, 2026 10:08
Route all Markdown (outline and full) through the line scanner. Full mode
uses Inline.parse, Src fences with options/pos_meta, latex env, quote
continuation, and heading anchors — ~7–9× vs master on logseq_large while
keeping outline_only ~15×.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
The generative MD fixture builder omitted the size field after it was
added to Type.Heading, which broke dune builds of that test helper.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
@tiensonqin
tiensonqin marked this pull request as ready for review August 30, 2026 00:27
Copilot AI lite review requested due to automatic review settings August 30, 2026 00:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Outline fast scan falls back to Angstrom Nested_link for [[a [[b]]]].
Property values use Property.property_references in both modes so nested
refs (and quoted values) match full parse. Add outline drawer tests.

Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
@cursor cursor Bot changed the title perf: MD outline ~15x + full Inline fast path (~2.3x) perf: MD outline ~15× + full parse ~8× via line scanner Aug 30, 2026
@tiensonqin
tiensonqin merged commit 1973758 into master Aug 30, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants